module lab5 (
    input clk,
    input rst,
    input [3:0] key_row,
    input [1:0] ra,
    input wr,
    input rd,
    input [1:0] m,
    input [1:0] key_sel,
    output [3:0] key_col,
    output [7:0] seg,
    output [2:0] sel
);

  wire [3:0] val;
  wire is_pressed;

  key u_key (
      clk,
      rst,
      key_row,
      key_col,
      val,
      is_pressed
  );

  reg [31:0] data;

  display u_display (
      clk,
      rst,
      data,
      8'b11001100,
      seg,
      sel
  );

  reg [7:0] pc;
  reg [7:0] r[0:3];

  reg [16:0] cnt;
  localparam CNT_MAX = 17'd99_999;

  always @(negedge clk or negedge rst) begin
    if (!rst) begin
      pc   <= 8'd0;
      r[0] <= 8'd0;
      r[1] <= 8'd0;
      r[2] <= 8'd0;
      r[3] <= 8'd0;
      data <= 32'd0;
      cnt  <= 17'd0;
    end else begin
      case (m)
        2'b00: begin
          pc <= 8'd0;
          data[23:16] <= 8'd0;
        end
        2'b01: begin
          if (key_sel[0] && is_pressed) begin
            case (key_sel[1])
              1'b0: begin
                pc[3:0] <= val;
                data[19:16] <= val;
              end
              1'b1: begin
                pc[7:4] <= val;
                data[23:20] <= val;
              end
            endcase
          end
        end
        2'b10: begin
          if (cnt == CNT_MAX) begin
            cnt <= 17'd0;
            pc <= pc + 1'b1;
            data[23:16] <= pc + 1'b1;
          end else begin
            cnt <= cnt + 1'b1;
          end
        end
        2'b11: begin
          if (cnt == CNT_MAX) begin
            cnt <= 17'd0;
            pc <= pc - 1'b1;
            data[23:16] <= pc - 1'b1;
          end else begin
            cnt <= cnt + 1'b1;
          end
        end
      endcase

      case ({
        wr, rd
      })
        2'b01: begin
          if (!key_sel[0] && is_pressed) begin
            case (key_sel[1])
              1'b0: begin
                data[3:0]  <= val;
                r[ra][3:0] <= val;
              end
              1'b1: begin
                data[7:4]  <= val;
                r[ra][7:4] <= val;
              end
            endcase
          end
        end
        2'b10: begin
          data[7:0] <= r[ra];
        end
      endcase
    end
  end

endmodule
